<?php
/**
 * Klasse für Tickets
 */
class Model_Invoice extends Zend_Db_Table_Abstract
{
    /** Table name */
    protected $_name = 'invoice';
	/** Primary Key */
    protected $_primary = 'iid';
    
    const STATUS_BILL = "bill";
    const STATUS_REMINDER1 = "reminder1";
    const STATUS_REMINDER2 = "reminder2";
    const STATUS_PAID = "paid";

    public function createDbRecord($data) {
    
    	$lastinsert_id = parent::insert($data);
    	return $lastinsert_id;
    	
    }
    
	public function getAll($where = null, $order = null, $count = null, $offset = null)
	{
		return $this->fetchAll($where, $order, $count, $offset);
	}
	/**
	 * Funktion um eine Rechnung zu erstellen
	 * 
     * @param array $projects  An array containing all the projects (IDs) that are supposed to be on the invoice.
     * @param array $user_info  An array containing all the user information.
     * @return ???
	 */
	public function writeInvoice($projects, $user_info)
	{				
		//Objekte der relevanten Klassen instanziieren
		$t = new Model_Ticket();
		$p = new Model_Project();
		$c = new Model_Cost();
		$b = new Model_Billing();
		$s = new Model_Settings();
		$rbi = new Model_RelBillingsInvoice();
		//PDF-Objekt instanziieren
		$pdf = new Ht_Pdf(PDF_PAGE_ORIENTATION, 'mm', PDF_PAGE_FORMAT, true, 'UTF-8', false);
		//Header & Footer Informationen
		$pdf->invoiceHeaderFooter();
		//Konfigurationsobjekt
		$conf = new Zend_Config_Ini(APPLICATION_PATH . '/config/app.ini', APPLICATION_ENVIRONMENT);
		//Currency Helper
		$currency = new Zend_Currency($conf->currency);
		$helper_currency = new Zend_View_Helper_Currency($currency);
		//Breitenangaben für die Tabellenfelder
		$w_pricefield = 30;
		$w_hoursfield = 20;
		//Rahmen und Füllfarbe für die Tabellenfelder
		$linestyle_header = array('width' => 0.8);
		$linestyle_default = array('width' => 0.2);
		$border = 1;
		$border = 0;
		$fields_bgcolor = true;	
		//Hintergrundfarbe	
		//$pdf->SetFillColor(230, 230, 230);
		$pdf->SetFillColor(255, 255, 255);
		//Mailadressen-Array
		$mail_arr = array();
		
		// add a page
		$pdf->AddPage();
				
		$pdf->SetFont('helvetica', '', 12);
		
		//PDF beginnt bei 45mm von oben
		$pdf->SetY(45);
		//Absenderadresse in klein
		$pdf->SetFont('helvetica', '', 6);
		$pdf->Write(0, 
					$s->getValueByName('company_name')." - ".$s->getValueByName('company_streetaddress')." - ".$s->getValueByName('company_zipcode')." ".$s->getValueByName('company_city'), 
					'', 0, 'L', 1, 0, false, false, 0);
		$pdf->Ln(2);		
		//Rechnungsadresse
		//normale Schrifgröße
		$pdf->SetFont('helvetica', '', 12);
		$pdf->Write(0, $user_info['company'], '', 0, 'L', 1, 0, false, false, 0);
		$pdf->Ln(0);
		$pdf->Write(0, $user_info['firstname']." ".$user_info['lastname'], '', 0, 'L', 1, 0, false, false, 0);
		$pdf->Ln(0);
		$pdf->Write(0, $user_info['streetaddress'], '', 0, 'L', 1, 0, false, false, 0);
		$pdf->Ln(0);
		$pdf->Write(0, $user_info['zipcode']." ".$user_info['city'], '', 0, 'L', 1, 0, false, false, 0);
		$pdf->Ln(2);
		
		//Rechnungsinformationen
		$pdf->Ln(12);
		$pdf->Write(0, "Rechnungsdatum: ".date("d.m.Y"), '', 0, 'R', 1, 0, false, false, 0);
		$pdf->Ln(0);
		$pdf->Write(0, "Rechnungsnummer: ".$s->getValueByName('current_invoice_number'), '', 0, 'R', 1, 0, false, false, 0);
		$pdf->Ln(0);
		//Lieferdatum vorerst wieder auskommentiert
		//$pdf->Write(0, "Lieferdatum:", '', 0, 'R', 1, 0, false, false, 0);
		//$pdf->Ln(0);
		
		//Anschreiben
		//@TODO: geschlechtsspezifische Anrede
		$pdf->Ln(8);
		$pdf->Write(0, "Sehr geehrte Damen und Herren,", '', 0, 'L', 1, 0, false, false, 0);
		$pdf->Ln(2);
		$pdf->Write(0, "hiermit erlaube ich mir für die von mir ausgeübte Tätigkeit wie folgt zu berechnen:", '', 0, 'L', 1, 0, false, false, 0);
		$pdf->Ln(10);
		
		//Tabellenheader (in Kursiv)
		$pdf->SetFont('helvetica', 'I', 12);
		$pdf->MultiCell(90, 0, '', $border, 'L', $fields_bgcolor, 0);
		$pdf->MultiCell($w_hoursfield, 0, 'Aufwand', $border, 'R', $fields_bgcolor, 0);
		$pdf->MultiCell($w_pricefield, 0, 'Preis', $border, 'R', $fields_bgcolor, 0);
		$pdf->MultiCell($w_pricefield, 0, 'Gesamt', $border, 'R', $fields_bgcolor, 1);
		$pdf->SetFont('helvetica', '', 12);
		$pdf->Line($pdf->GetX(), $pdf->GetY(), $pdf->GetX() + 170, $pdf->GetY(), $linestyle_header);
		$pdf->Ln(2);
		
		//Variablen zur Summierung der Beträge
		$total_amount = 0;
		//Tabelle mit den Tickets
		foreach($projects as $pid) {
			$pdf->Ln(4);
			$project = $p->getProjectByID($pid);
			//Projektname (in Fett)
			$pdf->SetFont('helvetica', 'B', 12);
			$pdf->Write(0, "Projekt: ".$project['ptitle'], '', 0, 'L', 1, 0, false, false, 0);
			$pdf->SetFont('helvetica', '', 12);
			$pdf->Ln(2);
			$tickets = $t->getTicketsByStatus(Model_Ticket::STATUS_TOBILL);
			foreach($tickets as $ticket) {
				//nur Tickets, die zum Projekt gehören!
				if($ticket['pid'] != $pid) continue;
				//Tickettitel
				//da der Tickettitel ausschlaggebend für die Höhe der Zeile ist, müssen wir
				//1. Höhe der Zeile errechnen (durch Subtraktion von altem und neuem Y-Wert)
				//2. 
				$y1 = $pdf->GetY();
				$pdf->MultiCell(90, 0, $ticket['ttitle'], $border, 'L', $fields_bgcolor, 1);
				$y2 = $pdf->GetY();
				$pdf->SetY($y1);
				//Stunden bzw. Pauschal
				$hours = ($ticket['flatrate'] == 0.00) ? $ticket['est_expense'] : "pauschal";
				$hours_txt = ($ticket['flatrate'] == 0.00) ? number_format($hours,2,',','.') : "pauschal";
				$pdf->MultiCell($w_hoursfield, 0, $hours_txt, $border, 'R', $fields_bgcolor, 0, $pdf->GetX() + 90);
				//Stundenpreis bzw. Pauschalpreis
				$price = ($ticket['flatrate'] == 0.00) ? $c->getPriceByCostID($ticket['costid']) : $ticket['flatrate'];
				$pdf->MultiCell($w_pricefield, 0, $helper_currency->currency($price), $border, 'R', $fields_bgcolor, 0);
				//Summe
				$sum = ($ticket['flatrate'] == 0.00) ? ($price * $hours) : $ticket['flatrate'];
				$pdf->MultiCell($w_pricefield, 0, $helper_currency->currency($sum), $border, 'R', $fields_bgcolor, 1);
				//Abschließender Trennstrich
				$pdf->SetY($y2);
				$pdf->Ln(1);
				$pdf->Line($pdf->GetX(), $pdf->GetY(), $pdf->GetX() + 170, $pdf->GetY(), $linestyle_default);
				//Summe auf Gesamtbetrag aufrechnen
				$total_amount += $sum;
				//Ticket als abgerechnet markieren
				$t->setStatus(Model_Ticket::STATUS_BILLED, $ticket['tid']);
				//Höhe für die nächste Position setzen
				//$pdf->SetXY($pdf->GetX(),$pdf->GetY() + 7);
				$pdf->Ln(2);
			}
			//Ein Array erstellen, welches alle Kontakt-Mailadressen der in der Rechnung enthaltenen
			//Projekte enthält. (jede nur 1x!)
			if(!in_array($project['contact_mail'], $mail_arr)) {
				array_push($mail_arr, $project['contact_mail']);
			}
			//Lieferzeitraum ausweisen
			$billing = $b->getBillinginformationByProjectID($pid);
			$pdf->Ln(2);
			$pdf->SetFont('helvetica', 'I', 12);
			switch($billing['repetition']) {
				case 'monthly':
					$lz_start = date("d.m.Y", strtotime("-1 month +1 day"));
					$lz_end = date("d.m.Y");
					break;
				case 'weekly':
					$lz_start = date("d.m.Y", strtotime("-1 week +1 day"));
					$lz_end = date("d.m.Y");
					break;
				case 'single':
				default:
					$lz_start = date("d.m.Y", $this->getStartDate($tickets));
					$lz_end = date("d.m.Y");
					break;
			}
			$pdf->MultiCell(90, 0, "Lieferzeitraum: ".$lz_start." - ".$lz_end, $border, 'L', $fields_bgcolor, 1);
			$pdf->SetFont('helvetica', '', 12);
		}
		//5mm Abstand zu den Tickets
		$pdf->SetXY($pdf->GetX(),$pdf->GetY() + 5);
		//Gesamtnettobetrag ausgeben
		$pdf->MultiCell(140, 0, "Nettobetrag", $border, 'L', $fields_bgcolor, 0);
		$pdf->MultiCell($w_pricefield, 0, $helper_currency->currency($total_amount), $border, 'R', $fields_bgcolor, 1);
		//MwSt errechnen
		$mwst = number_format(($total_amount / 100 * 19),2);
		$total_amount += $mwst;
		$pdf->MultiCell(140, 0, "zzgl. 19% Mehrwertsteuer", $border, 'L', $fields_bgcolor, 0);
		$pdf->MultiCell($w_pricefield, 0, $helper_currency->currency($mwst), $border, 'R', $fields_bgcolor, 1);
		$pdf->Ln(2);		
		//Gesamtbruttobetrag ausgeben (in Fett)
		$pdf->SetFont('helvetica', 'B', 12);
		$pdf->MultiCell(140, 0, "Rechnungsbetrag", $border, 'L', $fields_bgcolor, 0);
		$pdf->MultiCell($w_pricefield, 0, $helper_currency->currency($total_amount), $border, 'R', $fields_bgcolor, 1);		
		$pdf->SetFont('helvetica', '', 12);
		//Zahlungsziel der Rechnung
		$pdf->Ln(15);
		if($s->getValueByName('payment_target') > 0) {
			//Zahlungsziel ist in Tagen angegeben:
			$pay_target = time() + ($s->getValueByName('payment_target') * 86400);
			$pdf->Write(0, "Bitte überweisen Sie den Betrag bis zum ".date("d.m.Y",$pay_target)." auf das unten angegebene Konto.", '', 0, 'L', 1, 0, false, false, 0);			
		}
		else {
			$pdf->Write(0, "Bitte überweisen Sie den Betrag umgehend auf das unten angegebene Konto.", '', 0, 'L', 1, 0, false, false, 0);	
		}
		//Dateiname für die Rechnung
		$filename = "invoices/invoice-".$s->getValueByName('current_invoice_number').".pdf";
		//PDF erzeugen & Dateiberechtigungen vergeben
		$pdf->Output($filename, 'F');
		chmod ($filename, 0777);
		//Eintrag in die Datenbank
		$data['bid'] = "";
		$data['datesent'] = time();
		$data['pdflink'] = $filename;
		$data['status'] = self::STATUS_BILL;
		$iid = $this->createDbRecord($data);
		//Für jedes Projekt, dass auf der Rechnung landet, muss ein Eintrag in der DB gemacht werden
		foreach($projects as $pid) {
			$billing = $b->getBillinginformationByProjectID($pid);		
			$rbi->createRel(array("bid" => $billing['bid'], "iid" => $iid));
		}
		//Rechnungsnummer hochzählen
		$s->increaseInvoiceNumber();
		//Mail versenden
		foreach($mail_arr as $mail) {
			$this->sendInvoiceMail($mail, $filename);
		}
	}
	/**
	 * 
     * @param bool $ignorepaytime  Trigger if the scheduled time for the invoice is supposed to be ignored or not
     * @return ???
	 */
	public function writeDueInvoices($ignorepaytime = false) {
		//Objekte der relevanten Klassen instanziieren
		$t = new Model_Ticket();
		$b = new Model_Billing();
		$u = new Model_User();
		//Sammle aus den abrechenbaren Tickets die ProjektIDs ein
		$tickets = $t->getTicketsByStatus(Model_Ticket::STATUS_TOBILL)->toArray();
		//Extrahiere aus diesen Tickets die ProjektIDs
		$projects = array();
		foreach($tickets as $ticket) {
			//@TODO: Sonderfall: Ticket ist keinem Projekt zugeordnet - woher kommt dann die Rechnungsinfo?
			//vorerst werden diese Tickets nicht in Rechnungen einbezogen
			if($ticket['pid'] == 0) continue;
			if(!in_array($ticket['pid'], $projects)) array_push($projects, $ticket['pid']);
		}
		//Kunden-Array: hier hat jeder Kunde ein Array mit den abrechenbaren ProjektIDs
		$clients = array();
		//Prüfe für jedes Projekt, wann dieses abgerechnet werden soll
		foreach($projects as $pid) {
			//Infos aus der Billing-Tabelle
			$b_info = $b->getBillinginformationByProjectID($pid);
			//Unterarray für den jeweiligen User erstellen
			if(!is_array($clients[$b_info['clientid']])) $clients[$b_info['clientid']] = array();
			if(!$ignorepaytime) {
				//Fall 1: Einzelrechnung
				//=> prüfe, ob die Abrechnung am heutigen Tag stattfinden soll; wenn ja: alle Tickets dieses Projektes kommen auf die Rechnung
				if(date("d.m.Y",$b_info['paydate']) == date("d.m.Y")) {
					array_push($clients[$b_info['clientid']], $pid);
				}
				//Fall 2: Monatliche Rechnung
				//=> prüfe, ob die Abrechnung am heutigen Tag stattfinden soll; wenn ja: alle Tickets dieses Projektes kommen auf die Rechnung
				if($b_info['payday'] == date("d")) {
					array_push($clients[$b_info['clientid']], $pid);
				}
			}
			else {
				//alle Tickets dieses Projektes kommen auf die Rechnung
				array_push($clients[$b_info['clientid']], $pid);
			}
			//Prüfe ausserdem, ob der Kunde weitere Projekte mit verrechenbaren Tickets hat. Wenn ja, muss auch hier alles entsprechend geprüft werden,
			//damit alle Aufwände auf einer Rechnung stehen
			//...
		}
		//Rechnungen schreiben
		foreach($clients as $cid => $projectarray) {
			//@TODO: Prüfen, ob $projectarray leer ist!!
			if(!empty($projectarray)) {
				$this->writeInvoice($projectarray, $u->getUserBillingInformationByID($cid));
			}
		}
	}
	
	public function sendInvoiceMail($to, $file) {
		//Settings
		$s = new Model_Settings();
		//Mailobjekt
		$mail = new Zend_Mail('UTF-8');
	    
		//Mail-Metadaten
	    $mail->setFrom($s->getValueByName('invoicemail_frommail'), $s->getValueByName('invoicemail_fromname'));
	    $mail->addTo($to);
	    $mail->setSubject($s->getValueByName('invoicemail_subject'));
	    
	    //Mailtext
	    $text = $this->personalizeMailtext($s->getValueByName('invoicemail_text'));
	    $mail->setBodyText($text);
	    
	    //Anhang
	    $at = new Zend_Mime_Part(file_get_contents($file));
		$at->type        = 'application/pdf';
		$at->disposition = Zend_Mime::DISPOSITION_INLINE;
		$at->encoding    = Zend_Mime::ENCODING_BASE64;
		$at->filename    = substr($file, strpos($file, "/")+1);
		 
		$mail->addAttachment($at);
	    
		//Mail versenden
	    $mail->send();
	}
	
	public function personalizeMailtext($text) {	
		//Settings
		$s = new Model_Settings();
		
		//Anrede tauschen
		$text = str_replace("%salutation%", "Sehr geehrte Damen und Herren", $text);
		//Name des Absenders
		$text = str_replace("%sender_name%", $s->getValueByName('invoicemail_fromname'), $text);
		
		return $text;		
	}
	public function setStatus($status, $iid)
	{
    	$rows_updated = $this->update(array("status" => $status), $this->getAdapter()->quoteInto('iid = ?',$iid));
    	return $rows_updated;
	}
	/**
	 * Diese Funktion extrahiert aus den Tickets eines Projektes das frühste Bearbeitungs-/Erstellungsdatum. 
	 * 
     * @param array $tickets  Array aller Tickets eines Projektes
     * @return $timestamp
	 */
	public function getStartDate($tickets) {
		
		$timestamp = time();
		
		foreach($tickets as $ticket) {
			$ttime = ($ticket['processed'] > 0) ? $ticket['processed'] : $ticket['created'];
			if($ttime != 0 && $ttime < $timestamp) $timestamp = $ttime;
		}
		
		return $timestamp;
		
	}
 
};

?>